package cn.aresoft.excel.utils;

import cn.aresoft.excel.ExcelHandleException;
import cn.aresoft.excel.annotation.ExcelField;
import cn.aresoft.excel.annotation.ExcelValiate;
import cn.aresoft.configuration.PoiConfigProperties;
import cn.aresoft.excel.emuns.Direction;
import cn.aresoft.excel.emuns.ExcelDataFormat;
import cn.aresoft.excel.emuns.ExcelExportType;
import cn.aresoft.excel.entity.ExcelDictModel;
import cn.aresoft.excel.entity.ExcelFieldEntity;
import cn.aresoft.excel.entity.ExcelVaildateEntity;
import cn.aresoft.excel.entity.ExcelWrapEntity;
import cn.aresoft.excel.handle.IDictListGetHandler;
import cn.aresoft.excel.handle.IFieldValidateHandler;
import cn.aresoft.excel.handle.ISelfValueHandler;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author yangfeng
 * @description:
 * @date 2024/1/31 16:03
 */
@Component
public class ExcelFieldConfigUtil {

    @Autowired
    private PoiConfigProperties poiConfigProperties;

    /**
     * 获取导出字段对应单元格配置
     *
     * @param clazz           导出对象
     * @param excelExportType 1-导出数据，2-导出数据导入模版
     * @return List<ExcelFieldEntity>
     */
    public <T> List<ExcelFieldEntity> getExportFieldConfig(Class<? extends Object> clazz, ExcelExportType excelExportType, List<T> resultList) {
        try {
            Field[] fields = clazz.getDeclaredFields();
            List<ExcelFieldEntity> annotationList = new ArrayList<ExcelFieldEntity>();
            int column = 0;
            Direction direction = "1".equals(excelExportType.getType()) ? Direction.out : Direction.in;
            ExcelFieldEntity excelFieldEntity = null;
            for (Field field : fields) {
                field.setAccessible(true);
                ExcelField excelField = field.getAnnotation(ExcelField.class);
                if (excelField != null && (excelField.direction().equals(Direction.inout) || excelField.direction().equals(direction))) {
                    if (!excelField.isWrapField()) {
                        excelFieldEntity = new ExcelFieldEntity();
                        excelFieldEntity.setField(field);
                        excelFieldEntity.setIsWrapField(false);
                        excelFieldEntity.setColumn(column);
                        excelFieldEntity.setTitle(excelField.title());
                        getExcelFieldEntity(excelFieldEntity, excelField);
                        column++;
                        annotationList.add(excelFieldEntity);
                    } else {
                        if (!resultList.isEmpty() && List.class.isAssignableFrom(field.getType())) {
                            List valueList = (List) field.get(resultList.get(0));
                            Class<?> fieldClass = valueList.get(0).getClass();
                            for (int k = 0; k < valueList.size(); k++) {
                                for (Field subField : fieldClass.getDeclaredFields()) {
                                    subField.setAccessible(true);
                                    ExcelField subExcelField = subField.getAnnotation(ExcelField.class);
                                    ExcelWrapEntity excelWrapEntity = new ExcelWrapEntity();
                                    excelWrapEntity.setWrapFieldClazz(fieldClass);
                                    excelWrapEntity.setWrapListField(field);
                                    excelWrapEntity.setFieldSeq(k);
                                    excelFieldEntity = new ExcelFieldEntity();
                                    excelFieldEntity.setField(subField);
                                    excelFieldEntity.setIsWrapField(true);
                                    excelFieldEntity.setColumn(column);
                                    excelFieldEntity.setTitle(subExcelField.title()+(k+1));
                                    excelFieldEntity.setExcelWrapEntity(excelWrapEntity);
                                    getExcelFieldEntity(excelFieldEntity, subExcelField);
                                    column++;
                                    annotationList.add(excelFieldEntity);
                                }
                            }
                        }
                    }
                }
            }
            annotationList.sort(Comparator.comparingInt(ExcelFieldEntity::getSort));
            return annotationList;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据注解ExcelField获取字段配置属性
     * @param excelFieldEntity 字段属性对象
     * @param excelField  注解对象
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public void getExcelFieldEntity(ExcelFieldEntity excelFieldEntity, ExcelField excelField) throws InstantiationException, IllegalAccessException {

        IDictListGetHandler dictValueHandler = poiConfigProperties.getDictListGetHandler();
        Field field = excelFieldEntity.getField();
        if (field.getType().equals(String.class)) {
            excelFieldEntity.setPattern(ExcelDataFormat.TEXT.getFormat());
        } else if (field.getType().equals(Double.class) || field.getType().equals(Float.class) || field.getType().equals(BigDecimal.class)) {
            if (ExcelDataFormat.TEXT.equals(excelField.dataForm())) {   //如果没有设置单元格数据类型(默认格式是文本型)
                excelFieldEntity.setPattern(ExcelDataFormat.FIX_TWO.getFormat());
            } else {
                excelFieldEntity.setPattern(excelField.dataForm().getFormat());
            }
        } else if (field.getType().equals(Integer.class) || field.getType().equals(Long.class) || field.getType().equals(Short.class)) {
            if (ExcelDataFormat.TEXT.equals(excelField.dataForm())) {   //如果没有设置单元格数据类型(默认格式是文本型)
                excelFieldEntity.setPattern(ExcelDataFormat.INTEGER.getFormat());
            } else {
                excelFieldEntity.setPattern(excelField.dataForm().getFormat());
            }
        } else if (field.getType().equals(Date.class)) {
            if (ExcelDataFormat.TEXT.equals(excelField.dataForm())) {   //如果没有设置单元格数据类型(默认格式是文本型)
                excelFieldEntity.setPattern(ExcelDataFormat.DATE_SHORT2.getFormat());
            } else {
                excelFieldEntity.setPattern(excelField.dataForm().getFormat());
            }
        } else {
            excelFieldEntity.setPattern(excelField.dataForm().getFormat());
        }
        excelFieldEntity.setAlign(HorizontalAlignment.CENTER.getCode());
        excelFieldEntity.setSort(excelField.sort());
        excelFieldEntity.setWidth(excelField.width());
        excelFieldEntity.setRequired(excelField.required());
        excelFieldEntity.setCollapsed(excelField.collapsed());
        excelFieldEntity.setGroupName(excelField.groupName());
        if (StringUtils.isNotEmpty(excelField.dictTable())) {
            excelFieldEntity.setDictType(excelField.dictTable());
        } else if (StringUtils.isNotEmpty(excelField.dictType())) {
            excelFieldEntity.setDictType(excelField.dictType());
        }
        if (StringUtils.isNotEmpty(excelField.dictType()) && dictValueHandler != null) {
            List<ExcelDictModel> dictModelList = dictValueHandler.getFieldDictList(excelField.dictType(), excelField.dictTable(), excelField.dictType(), excelField.dicText());
            excelFieldEntity.setExcelDictModelList(dictModelList);
        } else if (!excelField.selfHandler().equals(ISelfValueHandler.class)) {
            ISelfValueHandler handlerObj = excelField.selfHandler().newInstance();
            excelFieldEntity.setSelfValueHandler(handlerObj);
        } else if (excelField.replacement().length > 0) {
            String[] replacement = excelField.replacement();
            List<ExcelDictModel> excelDictModelList = new ArrayList<ExcelDictModel>();
            ExcelDictModel excelDictModel = null;
            for (String dict : replacement) {
                String[] keyValue = dict.split("-");
                if (keyValue.length == 2) {
                    excelDictModel = new ExcelDictModel(keyValue[0], keyValue[1]);
                    excelDictModelList.add(excelDictModel);
                }
            }
            excelFieldEntity.setExcelDictModelList(excelDictModelList);
        }
        //新增校验逻辑
        if (field.isAnnotationPresent(ExcelValiate.class)) {
            ExcelVaildateEntity excelVaildateEntity = new ExcelVaildateEntity();
            ExcelValiate excelValiate = field.getAnnotation(ExcelValiate.class);
            excelVaildateEntity.setConstantStr(excelValiate.constantStr());
            excelVaildateEntity.setLength(excelValiate.length());
            excelVaildateEntity.setRules(excelValiate.rules());
            excelVaildateEntity.setSpecialChar(excelValiate.specialChar());
            if (!excelValiate.selfValidateHandler().equals(IFieldValidateHandler.class)) {
                //如果有设置个性化校验
                IFieldValidateHandler fieldValidateHandler = excelValiate.selfValidateHandler().newInstance();
                excelVaildateEntity.setFieldValidateHandler(fieldValidateHandler);
            }
            excelFieldEntity.setExcelVaildateEntity(excelVaildateEntity);
        }
    }

    /**
     * 获取导入字段单元格配置
     *
     * @param clazz   导出对象
     * @param headRow 表头
     * @return List<ExcelFieldEntity>
     */
    public List<ExcelFieldEntity> getImportFieldConfig(Class<? extends Object> clazz, Row headRow) throws Exception {

        IDictListGetHandler dictValueHandler = poiConfigProperties.getDictListGetHandler();
        Field[] fields = clazz.getDeclaredFields();
        short firstHeadCellNum = headRow.getFirstCellNum();
        short lastHeaderCellNum = headRow.getLastCellNum();
        List<ExcelFieldEntity> annotationList = new ArrayList<ExcelFieldEntity>();
        for (int i = firstHeadCellNum; i < lastHeaderCellNum; i++) {
            for (Field field : fields) {
                field.setAccessible(true);
                ExcelField excelField = field.getAnnotation(ExcelField.class);
                Cell headCell = headRow.getCell(i);
                if (headCell != null) {
                    headCell.setCellType(CellType.STRING);
                    if (excelField != null && headRow.getCell(i).getStringCellValue().equals(excelField.title())) {
                        ExcelFieldEntity excelFieldEntity = new ExcelFieldEntity();
                        excelFieldEntity.setField(field);
                        excelFieldEntity.setPattern(excelField.dataForm().getFormat());
                        excelFieldEntity.setSort(excelField.sort());
                        excelFieldEntity.setTitle(excelField.title());
                        excelFieldEntity.setWidth(excelField.width());
                        excelFieldEntity.setRequired(excelField.required());
                        excelFieldEntity.setColumn(i);
                        if (StringUtils.isNotEmpty(excelField.dictType()) && dictValueHandler != null) {
                            List<ExcelDictModel> dictModelList = dictValueHandler.getFieldDictList(excelField.dictType(), excelField.dictTable(), excelField.dictType(), excelField.dicText());
                            excelFieldEntity.setExcelDictModelList(dictModelList);
                        } else if (!excelField.selfHandler().equals(ISelfValueHandler.class)) {
                            ISelfValueHandler handlerObj = excelField.selfHandler().newInstance();
                            excelFieldEntity.setSelfValueHandler(handlerObj);
                        } else if (excelField.replacement().length > 0) {
                            String[] replacement = excelField.replacement();
                            List<ExcelDictModel> excelDictModelList = new ArrayList<>();
                            ExcelDictModel excelDictModel = null;
                            for (String dict : replacement) {
                                String[] keyValue = dict.split("-");
                                if (keyValue.length == 2) {
                                    excelDictModel = new ExcelDictModel(keyValue[0], keyValue[1]);
                                    excelDictModelList.add(excelDictModel);
                                }
                            }
                            excelFieldEntity.setExcelDictModelList(excelDictModelList);
                        }
                        //新增校验逻辑
                        if (field.isAnnotationPresent(ExcelValiate.class)) {
                            ExcelVaildateEntity excelVaildateEntity = new ExcelVaildateEntity();
                            ExcelValiate excelValiate = field.getAnnotation(ExcelValiate.class);
                            excelVaildateEntity.setConstantStr(excelValiate.constantStr());
                            excelVaildateEntity.setLength(excelValiate.length());
                            excelVaildateEntity.setRules(excelValiate.rules());
                            excelVaildateEntity.setSpecialChar(excelValiate.specialChar());
                            if (!excelValiate.selfValidateHandler().equals(IFieldValidateHandler.class)) {
                                //如果有设置个性化校验
                                IFieldValidateHandler fieldValidateHandler = excelValiate.selfValidateHandler().newInstance();
                                excelVaildateEntity.setFieldValidateHandler(fieldValidateHandler);
                            }
                            excelFieldEntity.setExcelVaildateEntity(excelVaildateEntity);
                        }
                        annotationList.add(excelFieldEntity);
                    }
                }
            }
        }
        if (annotationList.isEmpty()) {
            throw new ExcelHandleException("导入EXCEL文件数据格式不符合要求！");
        }
        return annotationList;
    }


}
